package com.sinoeyes.common.vo;

import com.sinoeyes.common.core.page.RestPageResult;
import com.sinoeyes.common.core.po.BasePo;
import com.sinoeyes.common.exception.BaseException;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * @author steven.zhang
 * @Description
 * @date 2019/10/10
 */
public abstract class BaseVo implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    /**
     * 将所有符合get/set拷贝规则的属性从PO对象拷贝到当前DTO对象，建议子类覆盖此方法。 <br/>
     * FIXME 拷贝需支持嵌套对象
     *
     * @param po
     */
    public <PO extends BasePo> void copyFrom(PO po) {

        if (po != null) {
            BeanUtils.copyProperties(po, this);
        }
    }

    /**
     * 将所有符合get/set拷贝规则的属性从当前DTO对象拷贝到PO对象，建议子类覆盖此方法。
     *
     * @param po
     */
    public <PO extends BasePo> void copyTo(PO po) {
        if (po != null) {
            BeanUtils.copyProperties(this, po);
        }
    }

    /**
     * 从PO拷贝一个新的VO对象，拷贝必须符合get/set拷贝规则。
     *
     * @param po
     * @param voClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> VO copyPo2Vo(PO po, Class<VO> voClazz) {
        if (po != null && voClazz != null) {
            VO vo = null;
            try {
                vo = voClazz.newInstance();
                vo.copyFrom(po);
            }
            catch (InstantiationException | IllegalAccessException e) {
                throw new BaseException(e.getMessage());
            }

            return vo;
        }

        return null;
    }

    /**
     * 从VO拷贝一个新的PO对象，拷贝必须符合get/set拷贝规则。
     *
     * @param vo
     * @param poClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> PO copyVo2Po(VO vo, Class<PO> poClazz) {
        if (vo != null && poClazz != null) {
            PO po = null;
            try {
                po = poClazz.newInstance();
                vo.copyTo(po);
            }
            catch (InstantiationException | IllegalAccessException e) {
                throw new BaseException(e.getMessage());
            }

            return po;
        }

        return null;
    }

    /**
     * 将一个PO列表(List)拷贝为一个新的VO列表(List)，拷贝必须符合get/set拷贝规则。
     *
     * @param poList
     * @param voClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> List<VO> copyPo2Vo(List<PO> poList,
                                                                                     Class<VO> voClazz) {
        List<VO> voList = new ArrayList<VO>();

        if (poList != null && voClazz != null) {
            for (PO po : poList) {
                voList.add(copyPo2Vo(po, voClazz));
            }
        }

        return voList;
    }

    /**
     * 将一个VO列表(List)拷贝为一个新的PO列表(List)，拷贝必须符合get/set拷贝规则。
     *
     * @param voList
     * @param poClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> List<PO> copyVo2Po(List<VO> voList,
                                                                                     Class<PO> poClazz) {
        List<PO> poList = new ArrayList<PO>();

        if (voList != null && poClazz != null) {
            for (VO vo : voList) {
                poList.add(copyVo2Po(vo, poClazz));
            }
        }

        return poList;
    }

    /**
     * 将一个PO列表(RestPageResult)拷贝为一个新的VO列表(RestPageResult)，拷贝必须符合get/set拷贝规则。
     *
     * @param poQr
     * @param voClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> RestPageResult<VO> copyPo2Vo(RestPageResult<PO> poQr,
                                                                                             Class<VO> voClazz) {
        RestPageResult<VO> voQr = new RestPageResult<VO>();

        if (poQr != null && voClazz != null) {
            voQr.setTotal(poQr.getTotal());
            for (PO po : poQr.getRows()) {
                voQr.getRows().add(copyPo2Vo(po, voClazz));
            }
        }

        return voQr;
    }

    /**
     * 将一个VO列表(RestPageResult)拷贝为一个新的PO列表(RestPageResult)，拷贝必须符合get/set拷贝规则。
     *
     * @param voQr
     * @param poClazz
     * @return
     */
    public final static <VO extends BaseVo, PO extends BasePo> RestPageResult<PO> copyVo2Po(RestPageResult<VO> voQr,
                                                                                            Class<PO> poClazz) {
        RestPageResult<PO> poQr = new RestPageResult<PO>();

        if (voQr != null && poClazz != null) {
            poQr.setTotal(voQr.getTotal());
            for (VO vo : voQr.getRows()) {
                poQr.getRows().add(copyVo2Po(vo, poClazz));
            }
        }

        return poQr;
    }

    /**
     * 从一种Vo拷贝为另一种Vo，拷贝必须符合get/set拷贝规则。
     *
     * @param fromVo
     * @param toVoClazz
     * @return
     */
    public final static <VO1 extends BaseVo, VO2 extends BaseVo> VO2 copyVo2Vo(VO1 fromVo,
                                                                                      Class<VO2> toVoClazz) {
        if (fromVo != null && toVoClazz != null) {
            VO2 toVo = null;
            try {
                toVo = toVoClazz.newInstance();
                BeanUtils.copyProperties(fromVo, toVo);
            }
            catch (InstantiationException | IllegalAccessException e) {
                throw new BaseException(e.getMessage());
            }

            return toVo;
        }

        return null;
    }

    /**
     * 将一个Vo列表(List)拷贝为一个新的VO列表(List)，拷贝必须符合get/set拷贝规则。
     *
     * @param fromVoList
     * @param toVoClazz
     * @return
     */
    public final static <VO1 extends BaseVo, VO2 extends BaseVo> List<VO2> copyVo2Vo(List<VO1> fromVoList,
                                                                                            Class<VO2> toVoClazz) {
        List<VO2> toVoList = new ArrayList<VO2>();

        if (fromVoList != null && toVoClazz != null) {
            for (VO1 fromVo : fromVoList) {
                toVoList.add(copyVo2Vo(fromVo, toVoClazz));
            }
        }

        return toVoList;
    }

    /**
     * 将一个VO列表(RestPageResult)拷贝为一个新的VO列表(RestPageResult)，拷贝必须符合get/set拷贝规则。
     *
     * @param fromVoQr
     * @param toVoClazz
     * @return
     */
    public final static <VO1 extends BaseVo, VO2 extends BaseVo> RestPageResult<VO2> copyVo2Vo(
            RestPageResult<VO1> fromVoQr, Class<VO2> toVoClazz) {
        RestPageResult<VO2> toDtoQr = new RestPageResult<VO2>();

        if (fromVoQr != null && toVoClazz != null) {
            toDtoQr.setTotal(fromVoQr.getTotal());
            for (VO1 vo : fromVoQr.getRows()) {
                toDtoQr.getRows().add(copyVo2Vo(vo, toVoClazz));
            }
        }

        return toDtoQr;
    }
}
